using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;

namespace Community.SharePoint.Commands
{
    
    public abstract class WebBaseCommand: Cmdlet 
    {
        List<SPWeb> _matchingWebs;
        List<SPWeb> _allWebs;
        SPWeb[] _input;
        internal  string[] _url;
        internal bool _disableWildCardReplacement;
        internal MatchMode _Mode;
        internal bool _recurse;
        internal bool _reverse;
        internal bool _force;

    [Parameter(Position = 0,
           ParameterSetName = "ByUrl",
           Mandatory = false,
           ValueFromPipelineByPropertyName = true,
           HelpMessage = "URL parameter accepts one or more comma-separated urls. Supports wildcards")]
        public String[] Url
        {
            get { return _url; }
            set
            {
                _Mode = MatchMode.ByURL;

                _url = value;
            }
        }

        [Parameter(ParameterSetName = "InputObject",
          Mandatory = true,
          ValueFromPipeline = true)]
        public SPWeb[] InputObject
        {
            get
            {
                return _input;
            }
            set
            {
                this._Mode = MatchMode.ByInput;
                this._input = value;
            }
        }
      
        [Parameter(
           Mandatory = false,
           ParameterSetName = "LiteralName",
           ValueFromPipeline = false,
           ValueFromPipelineByPropertyName = false)]
        public String[] LiteralUrl
        {
            get { return _url; }
            set
            {
                _Mode = MatchMode.ByURL;
                _disableWildCardReplacement = true;
                _url = value;
            }
        }

        [Parameter]

        public SwitchParameter Recurse
        {
            get
            {
                return this._recurse;
            }
            set
            {
                this._recurse = (bool)value;
            }
        }

        
        internal bool Reverse
        {
            get { return _reverse; }
            set { _reverse = value; }
        }
       internal List<SPWeb> AllWebs
       {
           get
           {
               if (_allWebs == null)
               {
                   _allWebs = GetAllWebs();
               }
               return _allWebs;
           }
       }
       
      

        protected WebBaseCommand()
        {
            _matchingWebs = new List<SPWeb>();
        }

        internal List<SPWeb> GetAllWebs()
        {
            List<SPWeb> webs = new List<SPWeb>();
            SPFarm farm = SPFarm.Local;

            SPWebServiceCollection webServs = new SPWebServiceCollection(farm);
            foreach (SPWebService webService in webServs)
            {
                SPWebApplicationCollection webApps = webService.WebApplications;
                foreach (SPWebApplication webApp in webApps)
                {
                    SPSiteCollection sites = webApp.Sites;
                    foreach (SPSite site in sites)
                    {
                        foreach (SPWeb web in site.AllWebs)
                        {
                            webs.Add(web);
                        }
                    }
                }
            }
             
            
            return webs;
        }

        internal List<SPWeb> MatchingWebs()
        {
            this._matchingWebs.Clear();

            switch (this._Mode)
            {
                case MatchMode.ByInput:
                    {
                        this.RetrieveMatchingWebsByInput();
                        break;
                    }

                default:
                    {
                        this.RetrieveMatchingWebsByURL();
                        break;
                    }
            }
            if (_reverse)
            { _matchingWebs.Reverse(); }
            return this._matchingWebs;
        }

        private void RetrieveMatchingWebsByURL()
        {
            if (this._url == null)
            {
                _matchingWebs = GetAllWebs();
            }
            else
            {
                foreach (string s in _url)
                {
                    if (_disableWildCardReplacement || !(WildcardPattern.ContainsWildcardCharacters(s)))
                    {
                        using (SPSite site = new SPSite(s))
                        {
                            using (SPWeb web = site.OpenWeb())
                            {
                                _matchingWebs.Add(web);
                                if (_recurse)
                                {
                                    foreach (SPWeb subWeb in web.Webs)
                                    {
                                        _matchingWebs.Add(subWeb);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        WildcardPattern wildCard = new WildcardPattern(s, WildcardOptions.IgnoreCase);

                        foreach (SPWeb web in AllWebs)
                        {
                            if (wildCard.IsMatch(web.Url))
                            {
                                _matchingWebs.Add(web);
                            }
                        }
                    }

                    
                }
            }
        }

        private void RetrieveMatchingWebsByInput()
        {
            if (this._input == null)
            {
                throw new System.Exception("Add Error handler here");
            }
            else
            {
                foreach (SPWeb web in _input)
                {
                    _matchingWebs.Add(web);
                    if (_recurse)
                    {
                        foreach (SPWeb subWeb in web.Webs)
                        {
                            _matchingWebs.Add(subWeb);
                        }
                    }
                }
            }
        }
    }
}
